﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Furion.Schedule;
using Furion;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;

namespace TimeJob.Core
{
    /// <summary>
    /// 作业持久化（数据库）
    /// </summary>
    public class DbJobPersistence : IJobPersistence
    {
        private readonly IServiceScopeFactory _scopeFactory;

        public DbJobPersistence(IServiceScopeFactory scopeFactory)
        {
            _scopeFactory = scopeFactory;
        }

        /// <summary>
        /// 作业调度服务启动时
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<SchedulerBuilder>> PreloadAsync(CancellationToken stoppingToken)    // Furion 4.9.1.59 之前为 public IEnumerable<SchedulerBuilder> Preload()
        {
            // 创建服务作用域
            using var serviceScope = _scopeFactory.CreateScope();
            var services = serviceScope.ServiceProvider;

            // 解析仓储
            var jobRepository = DbContext.Instance.GetSimpleClient<JobDetail>();
            var triggerRepository = DbContext.Instance.GetSimpleClient<JobTrigger>();

            // 获取所有定义的作业
            var allJobs = App.EffectiveTypes.ScanToBuilders();

            // 若数据库不存在任何作业，则直接返回
            if (!(await jobRepository.IsAnyAsync(u => true))) return allJobs;

            // 遍历所有定义的作业
            foreach (var schedulerBuilder in allJobs)
            {
                // 获取作业信息构建器
                var jobBuilder = schedulerBuilder.GetJobBuilder();

                // 加载数据库数据
                var dbDetail = await jobRepository.GetFirstAsync(u => u.JobId == jobBuilder.JobId);
                if (dbDetail == null) continue;

                // 同步数据库数据
                jobBuilder.LoadFrom(dbDetail);

                // 遍历所有作业触发器
                foreach (var (_, triggerBuilder) in schedulerBuilder.GetEnumerable())
                {
                    // 加载数据库数据
                    var dbTrigger = await triggerRepository.GetFirstAsync(u => u.JobId == jobBuilder.JobId && u.TriggerId == triggerBuilder.TriggerId);
                    if (dbTrigger == null) continue;

                    triggerBuilder.LoadFrom(dbTrigger)
                                  .Updated();   // 标记更新
                }

                // 标记更新
                schedulerBuilder.Updated();
            }

            return allJobs;
        }

        // ...

        public Task<SchedulerBuilder> OnLoadingAsync(SchedulerBuilder builder, CancellationToken stoppingToken) // Furion 4.9.1.59 之前为 public SchedulerBuilder OnLoading(SchedulerBuilder builder)
        {

            // 标记从其他地方更新，比如数据库
            return Task.FromResult(builder);
        }

        public Task OnChangedAsync(PersistenceContext context)
        {
            throw new NotImplementedException();
        }

        public Task OnTriggerChangedAsync(PersistenceTriggerContext context)
        {
            throw new NotImplementedException();
        }

        public Task OnExecutionRecordAsync(PersistenceExecutionRecordContext context)
        {
            throw new NotImplementedException();
        }
    }
}
